package com.lagou.sqlSession;

import com.lagou.pojo.Configuration;

import java.lang.reflect.*;
import java.util.List;

/**
 * @author <a href="mailto:zhouyong@cqyyt.com">zy</a>
 * @version 1.0
 * @date 2020/12/5 14:02
 */
public class DefaultSqlSession implements SqlSession {

    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    public <E> List<E> selectList(String statementid, Object... params) throws Exception {
        simpleExcutor simpleExcutor = new simpleExcutor();
        List<Object> list = simpleExcutor.query(configuration, configuration.getMap().get(statementid), params);
        return (List<E>) list;
    }

    public <T> T selectOne(String statementid, Object... params) throws Exception {
        List<Object> objects = selectList(statementid,params);
        if ( objects.size() == 1 ){
            return (T) objects.get(0);
        }else {
           throw new RuntimeException("查询为空或者查出多个数据");
        }
    }

    @Override
    public <T> T getMapper(Class<?> zy) {
        Object o = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{zy}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //方法名
                String methodName = method.getName();
                //接口名称
                String className = method.getDeclaringClass().getName();
                String statementId = className+"."+methodName;

                //准备参数 params = args
                //获取被调用方法的返回值类型
                Type genericReturnType = method.getGenericReturnType();
                //如果返回值类型是泛型，则是true
                if ( genericReturnType instanceof ParameterizedType){
                    List<Object> objects = selectList(statementId, args);
                    return objects;
                }else {
                    Object o1 = selectOne(statementId, args);
                    return o1;
                }
            }
        });

        return (T) o;
    }


}
